package controllers.examples;

import competition.MsPacManController;
import controllers.NearestPillDistance;
import controllers.PathPlanner;
import core.GameState;
import core.GameStateInterface;
import core.Node;
import core.utilities.Utilities;

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;

public class SmartPillEatingMsPacMan implements MsPacManController {

    private final NearestPillDistance npd;
    private final List<Node> history;
    private final int hLength = 10;

    public SmartPillEatingMsPacMan() {
        npd = new NearestPillDistance();
        history = new LinkedList<Node>();
    }

    private void rememberIfNew(Node cur) {
        if (history.size() == 0 || history.get(0) != cur) {
            history.add(0, cur);
            if (history.size() > hLength) {
                history.remove(history.size() - 1);
            }
        }
    }

    public int getAction(GameStateInterface gs) {
        Node current = gs.getPacman().current;

        rememberIfNew(current);
        npd.score(gs, current);

        PathPlanner pp = new PathPlanner(gs.getMaze());
        if (npd.closest == null) {

            System.out.println("Error: null target in PillEater.action");

            return 0;
        } else {

            ArrayList<Node> path = pp.getPath(current, npd.closest);
            Node next = path.get(0);
            int ret = Utilities.getDirection(current, next);
            if (distanceToTurn(path) < 4) {
                return nextDir;
            } else {
                return ret;
            }
        }
    }

    private static final int lookAhead = 5;
    private int nextDir = 0;

    int distanceToTurn(ArrayList<Node> path) {
        if (path.size() < 2 || history.size() == 0) return lookAhead;

        int cur = Utilities.getDirection(history.get(history.size() - 1), path.get(0));

        for (int i = 1; i < Math.min(lookAhead, path.size()); i++) {
            int dir = Utilities.getDirection(path.get(i - 1), path.get(i));
            if (dir != cur) {
                nextDir = dir;
                return i;
            }
        }
        return lookAhead;
    }
}